macro_rules! impl_into_bson {
    ($model:ty) => {
        impl From<$model> for wither::bson::Bson {
            fn from(m: $model) -> Self {
                wither::bson::to_bson(&m).unwrap_or(wither::bson::Bson::Null)
            }
        }
    };
}
macro_rules! impl_try_into_bson {
    ($model:ty) => {
        impl TryFrom<$model> for wither::bson::Bson {
            type Error = wither::bson::ser::Error;
            fn try_from(m: $model) -> Result<Self, Self::Error> {
                wither::bson::to_bson(&m)
            }
        }
    };
}
pub mod account;
pub mod article;
pub mod assets;
pub mod blacklist;
pub mod cache_sync;
pub mod club;
pub mod club_activity;
pub mod club_form;
pub mod club_form_status_flow;
pub mod club_log;
pub mod email_code;
pub mod invite;
pub mod like_list;
pub mod message;
pub mod page;
pub mod profile;
pub mod time_table;
pub mod user;
pub mod user_application;
pub mod user_login_log;
pub mod watch_record;
pub mod wechat_interactive;

pub use assets::Assets;
pub use club_form_status_flow::{ClubFormStatusFlow, ClubFormStatusFlowType};
use wither::{bson::doc, mongodb::options::FindOneAndUpdateOptions, Model};

use crate::{mdb::MDB, utils::db_utils::fixed_time_to_last_second, AppResult, ArcConfig};

macro_rules! sync_some_model {
    ($db:ident,$model:ty) => {
        log::info!(concat!("正在同步", stringify!($model)));
        <$model>::sync(&*$db).await?;
        log::info!(concat!(stringify!($model), "同步成功"));
    };
}

async fn sync_daily_module(db: MDB) -> AppResult<()> {
    let last_second =
        fixed_time_to_last_second(chrono::Utc::now(), chrono::FixedOffset::east(8 * 3600));
    let module_data = time_table::TaskTimeTableModel::with_type_and_time(
        time_table::TaskTimeTableType::Daily,
        wither::bson::DateTime::from_chrono(last_second),
    );
    let coll = time_table::TaskTimeTableModel::collection(&*db);
    let options = FindOneAndUpdateOptions::builder().upsert(true).build();
    coll.find_one_and_update(
        module_data.get_filter_document()?,
        doc! {"$set":module_data.document_from_instance()?},
        options,
    )
    .await?;
    Ok(())
}

pub async fn sync_models(db: MDB, config: ArcConfig) -> AppResult<()> {
    log::info!("同步models索引中...");
    sync_some_model!(db, cache_sync::CacheSyncModel);
    sync_some_model!(db, email_code::EmailCodeModel);
    sync_some_model!(db, club::ClubModel);
    sync_some_model!(db, article::ArticleModel);
    log::info!("同步models索引成功");
    if config.tasks.daily_clear.enable {
        log::info!("同步每日定时module中...");
        sync_daily_module(db.clone()).await?;
        log::info!("同步每日定时module成功");
    }
    Ok(())
}
